package com.dongzili.demo.customer.fulltext.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dongzili.demo.common.config.mybatisplus.MybatisPlusUtil;
import com.dongzili.demo.common.config.redis.RedisUtil;
import com.dongzili.demo.common.utils.ReflectUtils;
import com.dongzili.demo.customer.fulltext.analysis.IKAnalyzerSupport;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @描述：
 * @作者： 96511
 * @日期： 2025-01-06 23:07
 */
@Slf4j
//@Service
public class BaseService<T> {

    private final static String suffix = "_full_idx";//后缀
    private final Class<T> tClass;
    private final String indexName;
    private final String className;
    private final String primaryColumnKey;

    public BaseService(Class<T> tClass) {
        this.tClass = tClass;
        this.className = tClass.getSimpleName();
        this.indexName = this.className+suffix;
        this.primaryColumnKey = ReflectUtils.getPrimaryColumnKey(tClass);
    }

    public void syncIndex() throws InterruptedException {
        int current = 1;
        int size = 5000;
        LocalDateTime start = LocalDateTime.now();

        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc(primaryColumnKey);
        BaseMapper<T> mapper = MybatisPlusUtil.getMapper(tClass);
        Long total = mapper.selectCount(new LambdaQueryWrapper<>());
        long pages = (long) Math.ceil((double) total / size);
        for (int i = 1; i <= pages; i++){
            doSync(i, mapper, size, start);
        }
        log.info("同步索引启动，总共：{} 行，每页大小：{}, 总页数：{}", total, size, pages);
        log.info("同步索引开始，当前页：{}，每页大小：{}，耗时：{}", current, size, ChronoUnit.MILLIS.between(start, LocalDateTime.now()));

    }

    @Async
    public void doSync(int finalI,BaseMapper<T> mapper, int size, LocalDateTime start) {
        LocalDateTime currentStart = LocalDateTime.now();
        QueryWrapper<T> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc(primaryColumnKey);
        String lastLimit = " limit "+(finalI -1)* size +","+ size;
        wrapper.last(lastLimit);
        List<T> currentList = mapper.selectList(wrapper);
        Map<Object, T> map = currentList.stream().collect(Collectors.toMap(ReflectUtils::getPrimaryValue, t -> t));
        generateIndex(map);
        log.info("同步索引中...，当前页：{}，每页大小：{}，此页耗时：{}秒, 持续耗时：{}秒", finalI, size, ChronoUnit.SECONDS.between(currentStart, LocalDateTime.now()), ChronoUnit.SECONDS.between(start, LocalDateTime.now()));
        currentList = null;
        wrapper = null;
    }

    public void generateIndex(Map<Object, T> map) {
        SetOperations<String, Object> setOperations =  RedisUtil.getSetOperations();
        map.entrySet().parallelStream().forEach(entry -> {
            List<String> indexWords = ReflectUtils.getSearchIndexedData(entry.getValue());
            if(indexWords==null || indexWords.isEmpty()){
                return;
            }
            for (String text : indexWords){
                try{
                    List<String> parts = IKAnalyzerSupport.iKSegmenterToList(text);
                    for(String part : parts){
                        String key = indexName+":"+part;
                        setOperations.add(key, entry.getKey());
                    }
                }catch (Exception ignore){

                }
            }
        });
    }

}
